import warnings

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.ticker import PercentFormatter
import numpy as np

# 关闭字体查找警告
warnings.filterwarnings("ignore", category=UserWarning, module="matplotlib.font_manager")

# 设置中文显示（使用系统通用字体族，自动适配已安装字体）
plt.rcParams["font.family"] = ["sans-serif"]  # 通用无衬线字体族
plt.rcParams["font.sans-serif"] = ["Arial Unicode MS", "Heiti TC", "sans-serif"]  # 优先使用系统已安装的中文字体
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题


def load_stock_data(csv_path):
    """加载股票CSV数据并预处理"""
    try:
        df = pd.read_csv(csv_path)
        # 转换日期格式并排序
        df['日期'] = pd.to_datetime(df['日期'])
        df = df.sort_values(by='日期')
        # 提取股票代码（假设所有行都是同一股票，取第一行的代码）
        stock_code = df['股票代码'].iloc[0] if not df.empty else "未知代码"
        return df, stock_code
    except Exception as e:
        print(f"数据加载失败：{str(e)}")
        return None, None


def calculate_trend_line(prices, time_points):
    """计算趋势线参数"""
    slope, intercept = np.polyfit(time_points, prices, 1)
    return slope, intercept, intercept + slope * time_points


def plot_price_with_trends(df, stock_code):
    """绘制完整周期股价及多周期趋势线"""
    if df.empty:
        print("数据为空，无法绘制图表")
        return

    fig, ax = plt.subplots(figsize=(14, 8))

    # 绘制完整周期的收盘价
    ax.plot(df['日期'], df['收盘'], label='收盘价', color='blue', alpha=0.7, linewidth=1.5)

    # 生成时间序列（用于趋势线计算）
    time_points = np.arange(len(df))

    # 计算并绘制不同周期的趋势线
    # 1. 整体周期趋势线（长期趋势）
    slope_long, intercept_long, trend_line_long = calculate_trend_line(df['收盘'], time_points)
    ax.plot(df['日期'], trend_line_long, label='整体趋势线',
            color='black', linestyle='-', linewidth=2)

    # 2. 近期趋势线（例如：最后60天，中期趋势）
    if len(df) >= 60:
        recent_60_idx = -60
        slope_60, intercept_60, trend_line_60 = calculate_trend_line(
            df['收盘'].iloc[recent_60_idx:], time_points[recent_60_idx:])
        ax.plot(df['日期'].iloc[recent_60_idx:], trend_line_60, label='60天趋势线',
                color='red', linestyle='--', linewidth=2)

    # 3. 短期趋势线（例如：最后20天）
    if len(df) >= 20:
        recent_20_idx = -20
        slope_20, intercept_20, trend_line_20 = calculate_trend_line(
            df['收盘'].iloc[recent_20_idx:], time_points[recent_20_idx:])
        ax.plot(df['日期'].iloc[recent_20_idx:], trend_line_20, label='20天趋势线',
                color='green', linestyle='-.', linewidth=2)

    # 计算趋势角度并标注
    trend_angle_long = np.degrees(np.arctan(slope_long))
    trend_dir_long = "上升" if trend_angle_long > 0 else "下降"

    # 在图表上标注整体趋势信息
    ax.text(0.05, 0.95,
            f'整体趋势角度: {trend_angle_long:.2f}° ({trend_dir_long})',
            transform=ax.transAxes, fontsize=12,
            verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.7))

    ax.set_title(f'{stock_code} 股价走势及多周期趋势线', fontsize=16)
    ax.set_xlabel('日期', fontsize=12)
    ax.set_ylabel('价格（元）', fontsize=12)

    # 日期格式设置
    ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45)

    # 添加网格和图例
    ax.grid(linestyle='--', alpha=0.6)
    ax.legend(loc='best')

    plt.tight_layout()
    plt.show()


def plot_close_price(df, stock_code):
    """绘制收盘价走势"""
    fig, ax = plt.subplots(figsize=(12, 6))
    ax.plot(df['日期'], df['收盘'], label='收盘价', color='blue', linewidth=2)

    ax.set_title(f'{stock_code} 收盘价走势', fontsize=15)
    ax.set_xlabel('日期', fontsize=12)
    ax.set_ylabel('价格（元）', fontsize=12)

    # 日期格式设置
    ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45)

    ax.grid(linestyle='--', alpha=0.7)
    ax.legend()
    plt.tight_layout()
    plt.show()


def plot_price_range(df, stock_code):
    """绘制开盘价、收盘价、最高价、最低价对比"""
    fig, ax = plt.subplots(figsize=(12, 6))
    ax.plot(df['日期'], df['开盘'], label='开盘价', color='orange', linestyle='--')
    ax.plot(df['日期'], df['收盘'], label='收盘价', color='blue', linewidth=2)
    ax.plot(df['日期'], df['最高'], label='最高价', color='red', linestyle=':')
    ax.plot(df['日期'], df['最低'], label='最低价', color='green', linestyle=':')

    ax.set_title(f'{stock_code} 价格区间对比', fontsize=15)
    ax.set_xlabel('日期', fontsize=12)
    ax.set_ylabel('价格（元）', fontsize=12)

    ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45)

    ax.grid(linestyle='--', alpha=0.7)
    ax.legend()
    plt.tight_layout()
    plt.show()


def plot_change_and_volume(df, stock_code):
    """绘制涨跌幅（副轴）和成交量（主轴）"""
    fig, ax1 = plt.subplots(figsize=(12, 6))

    # 主轴：成交量（柱状图）
    ax1.bar(df['日期'], df['成交量'], label='成交量', color='gray', alpha=0.6)
    ax1.set_xlabel('日期', fontsize=12)
    ax1.set_ylabel('成交量', fontsize=12)
    ax1.tick_params(axis='y')

    # 副轴：涨跌幅（折线图，百分比显示）
    ax2 = ax1.twinx()
    ax2.plot(df['日期'], df['涨跌幅'], label='涨跌幅', color='red', linewidth=2)
    ax2.set_ylabel('涨跌幅', fontsize=12)
    ax2.yaxis.set_major_formatter(PercentFormatter(xmax=100))  # 显示为百分比
    ax2.tick_params(axis='y')

    # 合并图例
    lines1, labels1 = ax1.get_legend_handles_labels()
    lines2, labels2 = ax2.get_legend_handles_labels()
    ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left')

    ax1.set_title(f'{stock_code} 成交量与涨跌幅', fontsize=15)
    ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45)

    ax1.grid(linestyle='--', alpha=0.7)
    plt.tight_layout()
    plt.show()


def plot_turnover_rate(df, stock_code):
    """绘制换手率走势"""
    fig, ax = plt.subplots(figsize=(12, 6))
    ax.plot(df['日期'], df['换手率'], label='换手率', color='purple', linewidth=2)

    ax.set_title(f'{stock_code} 换手率走势', fontsize=15)
    ax.set_xlabel('日期', fontsize=12)
    ax.set_ylabel('换手率', fontsize=12)
    ax.yaxis.set_major_formatter(PercentFormatter(xmax=100))  # 百分比显示

    ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45)

    ax.grid(linestyle='--', alpha=0.7)
    ax.legend()
    plt.tight_layout()
    plt.show()


if __name__ == "__main__":
    # 替换为你的股票CSV文件路径
    # csv_path = "../crud/shina_600000_2024.csv"
    # csv_path = "../crud/shina_600029_all.csv"
    csv_path = "../crud/shina_600081_all.csv"

    # 加载数据
    stock_df, code = load_stock_data(csv_path)
    if stock_df is not None:
        # 依次绘制各类图表
        plot_close_price(stock_df, code)  # 收盘价走势
        plot_price_range(stock_df, code)  # 价格区间对比
        plot_price_with_trends(stock_df, code)  # 完整周期股价及趋势线（新增）
        plot_change_and_volume(stock_df, code)  # 成交量与涨跌幅
        plot_turnover_rate(stock_df, code)  # 换手率走势
